﻿import ko = require("knockout");
import Project = require("Project");
import Track = require("Track");
import Clip = require("Clip");

class Selection {
    public constructor(public project: Project) {}

    start: KnockoutObservable<number> = ko.observable(0);

    stop: KnockoutObservable<number> = ko.observable(0);

    length: KnockoutComputed<number> = ko.pureComputed({
        read: () => this.stop() - this.start(),
        write: (value) => {
            this.stop(this.start() + ko.unwrap(value));
        }
    });

    clips: KnockoutComputed<Clip[]> = ko.pureComputed(() =>
        this.tracks().reduce(
            (prev: Clip[], cur: Track) => prev.concat(
                cur.clips().filter(
                    (val: { clip: Clip, offset: number }) => val.offset >= this.start() && val.offset + val.clip.duration() < this.stop()
                    ).map(
                    (val: { clip: Clip, offset: number }) => val.clip
                    )
                ),
            []
            )
        );

    containedClips = this.clips;

    touchedClips: KnockoutComputed<Clip[]> = ko.pureComputed(() =>
        this.tracks().reduce(
            (prev: Clip[], cur: Track) => prev.concat(
                cur.clips().filter(
                    (val: { clip: Clip, offset: number }) => !(this.start() >= val.offset + val.clip.duration() && this.stop() < val.offset )
                    ).map(
                    (val: { clip: Clip, offset: number }) => val.clip
                    )
                ),
            []
            )
        );

    trackStart: KnockoutObservable<number> = ko.observable(0);

    trackStop: KnockoutObservable<number> = ko.observable(0);

    trackLength: KnockoutComputed<number> = ko.pureComputed({
        read: () => this.trackStop() - this.trackStart(),
        write: (value) => {
            this.trackStop(this.trackStart() + ko.unwrap(value));
        }
    });

    tracks: KnockoutComputed<Track[]> = ko.pureComputed(() =>
        this.project.tracks().slice(
            this.trackStart(),
            this.trackStop()
        )
    );

    public setTime(start: number, stop: number) {
        this.start(start);
        this.stop(stop);
        return this;
    }

    public setTracks(start: number, stop: number) {
        this.trackStart(start);
        this.trackStop(stop);
        return this;
    }

    public selectClip(clip: Clip) {
        var tracks = this.project.tracks();
        var trackIndex = null;
        for (let i = 0; i < tracks.length; i++) {
            if (tracks[i].track.hasClip(clip)) {
                trackIndex = i;
                break;
            }
        }

        if (trackIndex === null) {
            throw new Error("Clip doesn't belong to any track in the project");
        }

        this.trackStart(trackIndex);
        this.trackStop(trackIndex);

        var clips = tracks[trackIndex].clips();
        for (let i = 0; i < clips.length; i++) {
            if (clips[i].clip === clip) {
                this.start(clips[i].offset);
                this.stop(clips[i].offset +clips[i].clip.duration());
                break;
            }
        }
    }
}

export = Selection;